package com.njtoyo.taxi.admin.service.data.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njtoyo.taxi.admin.handler.FilterHandler;
import com.njtoyo.taxi.admin.handler.common.DateIntervalHandler;
import com.njtoyo.taxi.admin.logic.data.RankListLogic;
import com.njtoyo.taxi.admin.mapper.master.entity.Company;
import com.njtoyo.taxi.admin.mapper.master.entity.Driver;
import com.njtoyo.taxi.admin.mapper.master.enums.RankListTimeRangeType;
import com.njtoyo.taxi.admin.mapper.master.mapper.CompanyMapper;
import com.njtoyo.taxi.admin.mapper.master.mapper.DriverMapper;
import com.njtoyo.taxi.admin.mapper.secondary.enums.dashboard.TimeIntervalType;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.*;
import com.njtoyo.taxi.admin.rest.presenter.platfrom.AdminUserIdentityPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.data.data_analysis.RankListWrapper;
import com.njtoyo.taxi.admin.service.data.RankListService;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class RankListServiceImpl implements RankListService {

    @Autowired
    private RankListLogic rankListLogic;

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Override
    public RestResult rankList(AdminUser adminUser, RankListWrapper wrapper) {
        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());
        List<Long> isImitates = filterHandler.getIsImitates();

        // 校验时间类型参数
        if (RankListTimeRangeType.customize.equals(wrapper.getTimeType())) {
            if (Objects.isNull(wrapper.getStartTime()) || Objects.isNull(wrapper.getEndTime())) {
                return RestResult.failed("开始时间或结束时间不能为空");
            }

            if (wrapper.getEndTime().before(wrapper.getStartTime())) {
                return RestResult.failed("开始时间不能晚于结束时间");
            }
        }

        // 根据账号类型，分发请求
        switch (adminUser.getAccountType()) {
            case platform:
                RankListForPlatformPresenter rankListForPlatformPresenter = rankListForPlatform(isImitates, wrapper);
                return RestResult.success(rankListForPlatformPresenter);
            case canton:
                List<Long> companyIds = new ArrayList<>();

                // 校验请求参数中是否指定了区域
                if (Objects.nonNull(wrapper.getCantonId())) {
                    // 校验是否指定了公司
                    if (Objects.nonNull(wrapper.getCompanyId())) {
                        // 若指定区域，且指定公司，则使用指定的公司id
                        companyIds.add(wrapper.getCompanyId());
                    } else {
                        // 若指定区域，未指定公司，则获取指定区域的公司列表
                        companyIds = companyMapper.selectList(new QueryWrapper<Company>().eq("canton_id", wrapper.getCantonId()))
                                .stream().map(Company::getId).collect(Collectors.toList());
                    }
                } else {
                    // 未指定区域，则获取账号对应的公司列表
                    AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();
                    companyIds = identity.getCompanyIds();
                }

                if (0 == companyIds.size()) {
                    RankListForCantonPresenter rankListForCantonPresenter = new RankListForCantonPresenter();
                    rankListForCantonPresenter.setRank(new ArrayList<>());
                    rankListForCantonPresenter.setType("company");
                    return RestResult.success(rankListForCantonPresenter);
                }

                RankListForCantonPresenter rankListForCantonPresenter = rankListForCanton(isImitates, wrapper, companyIds);
                return RestResult.success(rankListForCantonPresenter);
            case company:
                List<Long> companyList = new ArrayList<>();
                RankListForCompanyPresenter rankListForCompanyPresenter = new RankListForCompanyPresenter();

                // 校验是否指定了公司
                if (Objects.nonNull(wrapper.getCompanyId())) {
                    companyList.add(wrapper.getCompanyId());
                } else {
                    // 未指定，则根据账号所管理的公司ids
                    AdminUserIdentityPresenter identityForCompany = (AdminUserIdentityPresenter) adminUser.getIdentity();
                    companyList = identityForCompany.getCompanyIds();

                    if (0 == companyList.size()) {
                        rankListForCompanyPresenter.setRank(new ArrayList<>());
                        rankListForCompanyPresenter.setType("driver");
                        return RestResult.success(rankListForCompanyPresenter);
                    }
                }

                // 获取公司下属所有司机ids
                List<Driver> driverList = driverMapper.getDriverListByCompanyIds(companyList);

                if (0 == driverList.size()) {
                    rankListForCompanyPresenter.setRank(new ArrayList<>());
                    rankListForCompanyPresenter.setType("driver");
                    return RestResult.success(rankListForCompanyPresenter);
                }

                rankListForCompanyPresenter = rankListForCompany(wrapper, driverList);
                return RestResult.success(rankListForCompanyPresenter);
        }

        return RestResult.fail();
    }

    @Override
    public RestResult rankSubList(AdminUser adminUser, RankListWrapper wrapper) {
        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());
        List<Long> isImitates = filterHandler.getIsImitates();

        // 校验时间类型参数
        if (RankListTimeRangeType.customize.equals(wrapper.getTimeType())) {
            if (Objects.isNull(wrapper.getStartTime()) || Objects.isNull(wrapper.getEndTime())) {
                return RestResult.failed("开始时间或结束时间不能为空");
            }

            if (wrapper.getEndTime().before(wrapper.getStartTime())) {
                return RestResult.failed("开始时间不能晚于结束时间");
            }
        }

        // 根据父级类型，分发请求
        switch (wrapper.getParentType()) {
            case canton:
                // 获取该区域内的公司ids
                List<Long> companyIds = companyMapper.selectList(new QueryWrapper<Company>().eq("canton_id", wrapper.getParentId()))
                        .stream().map(Company::getId).collect(Collectors.toList());

                if (0 == companyIds.size()) {
                    RankListForCantonPresenter rankListForCantonPresenter = new RankListForCantonPresenter();
                    rankListForCantonPresenter.setRank(new ArrayList<>());
                    rankListForCantonPresenter.setType("company");
                    return RestResult.success(rankListForCantonPresenter);
                }

                RankListForCantonPresenter rankListForCantonPresenter = rankListForCanton(isImitates, wrapper, companyIds);
                return RestResult.success(rankListForCantonPresenter);
            case company:
                RankListForCompanyPresenter rankListForCompanyPresenter = new RankListForCompanyPresenter();

                // 获取该区域内的公司ids
                List<Long> companyList = new ArrayList<>();
                companyList.add(wrapper.getParentId());

                // 根据公司获取司机列表
                List<Driver> driverList = driverMapper.getDriverListByCompanyIds(companyList);

                if (0 == driverList.size()) {
                    rankListForCompanyPresenter.setRank(new ArrayList<>());
                    rankListForCompanyPresenter.setType("driver");
                    return RestResult.success(rankListForCompanyPresenter);
                }

                rankListForCompanyPresenter = rankListForCompany(wrapper, driverList);
                return RestResult.success(rankListForCompanyPresenter);
        }

        return RestResult.fail();
    }

    // 获取【区域】类型rankList(平台类型账号)
    private RankListForPlatformPresenter rankListForPlatform(List<Long> isImitates, RankListWrapper wrapper) {
        // 开始、结束时间
        Date startTime;
        Date endTime;

        // 上个周期对比的开始、结束时间
        Date comparisonStartTime;
        Date comparisonEndTime;

        RankListForPlatformPresenter res = new RankListForPlatformPresenter();
        List<RankListCantonPresenter> list = new ArrayList<>();

        // 判断rankListType
        // 今日、本周、本月都可以从minute缓存数据获取，自定义从daily获取
        switch (wrapper.getTimeType()) {
            case customize:
                // 自定义
                startTime = DateUtil.beginOfMonth(wrapper.getStartTime());
                endTime = DateUtil.endOfMonth(wrapper.getEndTime());

                // 间隔月数
                int IntervalMonth = DateIntervalHandler.intervalMonth(startTime, endTime);

                int interval = Math.negateExact(IntervalMonth + 1);

                // 对比
                comparisonStartTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(startTime, interval));
                comparisonEndTime = DateUtil.endOfMonth(DateUtil.offsetMonth(endTime, interval));

                list = rankListLogic.getListFromDailyForPlatform(wrapper.getTimeType(), isImitates, startTime, endTime, comparisonStartTime, comparisonEndTime);
                break;
            case day:
                // 今日
                startTime = DateUtil.beginOfDay(DateUtil.date());
                endTime = DateUtil.date();

                // 昨日
                comparisonStartTime = DateUtil.beginOfDay(DateUtil.yesterday());
                comparisonEndTime = DateUtil.yesterday();

                list = rankListLogic.getListFromMinuteForPlatform(wrapper.getTimeType(), isImitates, startTime, endTime, comparisonStartTime, comparisonEndTime);
                break;
            case week:
                // 本周
                startTime = DateUtil.beginOfWeek(DateUtil.date());
                endTime = DateUtil.date();

                // 上周
                comparisonStartTime = DateUtil.beginOfWeek(DateUtil.lastWeek());
                comparisonEndTime = DateUtil.lastWeek();

                list = rankListLogic.getListFromMinuteForPlatform(wrapper.getTimeType(), isImitates, startTime, endTime, comparisonStartTime, comparisonEndTime);
                break;
            case month:
                // 本月
                startTime = DateUtil.beginOfMonth(DateUtil.date());
                endTime = DateUtil.date();

                // 上月
                comparisonStartTime = DateUtil.beginOfMonth(DateUtil.lastMonth());
                comparisonEndTime = DateUtil.lastMonth();

                list = rankListLogic.getListFromMinuteForPlatform(wrapper.getTimeType(), isImitates, startTime, endTime, comparisonStartTime, comparisonEndTime);
                break;
        }

        res.setRank(list);
        res.setType("canton");

        return res;
    }

    // 获取【公司】类型rankList(区域类型账号)
    private RankListForCantonPresenter rankListForCanton(List<Long> isImitates, RankListWrapper wrapper, List<Long> companyIds) {
        // 开始、结束时间
        Date startTime;
        Date endTime;

        RankListForCantonPresenter res = new RankListForCantonPresenter();
        List<RankListCompanyPresenter> list = new ArrayList<>();

        // 判断rankListType
        // 今日、本周、本月都可以从minute缓存数据获取
        switch (wrapper.getTimeType()) {
            case customize:
                // 自定义-月范围
                startTime = DateUtil.beginOfMonth(wrapper.getStartTime());
                endTime = DateUtil.endOfMonth(wrapper.getEndTime());

                list = rankListLogic.getListFromDailyForCanton(wrapper.getTimeType(), isImitates, startTime, endTime, companyIds);
                break;
            case day:
                // 今日
                startTime = DateUtil.beginOfDay(DateUtil.date());
                endTime = DateUtil.date();

                list = rankListLogic.getListFromMinuteForCanton(wrapper.getTimeType(), isImitates, startTime, endTime, companyIds);
                break;
            case week:
                // 本周
                startTime = DateUtil.beginOfWeek(DateUtil.date());
                endTime = DateUtil.date();

                list = rankListLogic.getListFromMinuteForCanton(wrapper.getTimeType(), isImitates, startTime, endTime, companyIds);
                break;
            case month:
                // 本月
                startTime = DateUtil.beginOfMonth(DateUtil.date());
                endTime = DateUtil.date();

                list = rankListLogic.getListFromMinuteForCanton(wrapper.getTimeType(), isImitates, startTime, endTime, companyIds);
                break;
        }

        res.setRank(list);
        res.setType("company");

        return res;
    }

    // 获取【司机】类型rankList(公司类型账号)
    private RankListForCompanyPresenter rankListForCompany(RankListWrapper wrapper, List<Driver> driverList) {
        // 开始、结束时间
        Date startTime;
        Date endTime;
        RankListForCompanyPresenter res = new RankListForCompanyPresenter();
        List<RankListDriverPresenter> list = new ArrayList<>();

        // 判断rankListType
        // 今日、本周、本月都可以从minute缓存数据获取
        switch (wrapper.getTimeType()) {
            case customize:
                // 自定义-月范围
                startTime = DateUtil.beginOfMonth(wrapper.getStartTime());
                endTime = DateUtil.endOfMonth(wrapper.getEndTime());
                list = rankListLogic.getListForCompany(TimeIntervalType.daily, startTime, endTime, driverList);
                break;
            case day:
                // 今日
                startTime = DateUtil.beginOfDay(DateUtil.date());
                endTime = DateUtil.date();

                list = rankListLogic.getListForCompany(TimeIntervalType.minute, startTime, endTime, driverList);
                break;
            case week:
                // 本周
                startTime = DateUtil.beginOfWeek(DateUtil.date());
                endTime = DateUtil.date();

                list = rankListLogic.getListForCompany(TimeIntervalType.minute, startTime, endTime, driverList);
                break;
            case month:
                // 本月
                startTime = DateUtil.beginOfMonth(DateUtil.date());
                endTime = DateUtil.date();

                list = rankListLogic.getListForCompany(TimeIntervalType.minute, startTime, endTime, driverList);
                break;
        }

        res.setRank(list);
        res.setType("driver");

        return res;
    }
}
